using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Collections.Generic;

/// <summary>
/// Summary description for ReportBuilder
/// </summary>

public class ReportBuilder
{
    private List<Part> parts;
    private List<Answer> userAnswers;
    private Control control;
    private List<int> avoidanceItems;

    private List<Conflict> conflict;
    private List<Question> importance;
    private List<Question> presured;
    private List<UnderAchieved> underAchived;

    private int CompareQuestions(Question q1, Question q2)
    {
        int a1 = Convert.ToInt32(q1.Answer.Ans);
        int a2 = Convert.ToInt32(q2.Answer.Ans);
        if (a1 < a2)
            return 1;
        else if (a1 > a2)
            return -1;
        return 0;
    }

    private int CompareUnderAchieved(UnderAchieved c1, UnderAchieved c2)
    {
        if (c1.Socre < c2.Socre)
            return 1;
        else if (c1.Socre > c2.Socre)
            return -1;
        return 0;
    }

    private int CompareConflicts(Conflict c1, Conflict c2)
    {
        if (c1.Socre < c2.Socre)
            return 1;
        else if (c1.Socre > c2.Socre)
            return -1;
        return 0;
    }

    public ReportBuilder(IEnumerable<Part> parts, IEnumerable<Answer> answers)
    {
        control = new Control();
        avoidanceItems = new List<int>();
        populateAvoidanceItems();
        this.parts = (List<Part>)parts;
        this.userAnswers = (List<Answer>)answers;
        MatchAnswerQuestions();
        CalculateAvoidanceItems();
        foreach (Question qImportance in this.parts[0].Questions)
        {
            importanceScore += Convert.ToInt32(qImportance.Answer.Ans);
        }
        importanceScore /= this.parts[0].Questions.Count;

        foreach (Question qPressure in this.parts[1].Questions)
        {
            pressureScore += Convert.ToInt32(qPressure.Answer.Ans);
        }
        pressureScore /= this.parts[1].Questions.Count;

        //int yesAnswerNo = 0;
        //foreach (Question qSuccess in this.parts[2].Questions)
        //{
        //    activityScore += Convert.ToInt32(qSuccess.Answer.Ans);
        //    if (qSuccess.Answer.Ans != null)
        //        yesAnswerNo++;
        //}
        //if (yesAnswerNo != 0)
        //    successScore = activityScore / yesAnswerNo;
        int successAns = 0;
        int yesAnswerNo = 0;
        foreach (Question qSuccess in this.parts[2].Questions)
        {
            successAns += Convert.ToInt32(qSuccess.Answer.Ans);
            if (Convert.ToInt32(qSuccess.Answer.Ans) != 0l)
                yesAnswerNo++;
        }
        if (yesAnswerNo != 0)
            successScore = successAns / yesAnswerNo;
        this.activityScore = yesAnswerNo;
    }

    private void populateAvoidanceItems()
    {
        string[] strItems = ConfigurationManager.AppSettings["AvoidanceItems"].ToString().Split(',');
        foreach (string str in strItems)
        {
            int i = Convert.ToInt32(str.Trim());
            avoidanceItems.Add(i);
        }
    }

    private void MatchAnswerQuestions()
    {
        List<Question> importance = (List<Question>)parts[0].Questions;
        List<Question> pressured = (List<Question>)parts[1].Questions;
        List<Question> sccuss = (List<Question>)parts[2].Questions;
        int questionIndex = 0, userAnswerIndex = 0;
        for (questionIndex = 0; questionIndex < importance.Count; questionIndex++)
        {
            if (userAnswerIndex < userAnswers.Count && userAnswers[userAnswerIndex].Number == importance[questionIndex].ID)
            {
                importance[questionIndex].Answer = userAnswers[userAnswerIndex];
                userAnswerIndex++;
            }
        }
        for (questionIndex = 0; questionIndex < pressured.Count; questionIndex++)
        {
            if (userAnswerIndex < userAnswers.Count && userAnswers[userAnswerIndex].Number == pressured[questionIndex].ID)
            {
                pressured[questionIndex].Answer = userAnswers[userAnswerIndex];
                userAnswerIndex++;
            }
        }

        for (questionIndex = 0; questionIndex < sccuss.Count; questionIndex++)
        {
            if (userAnswerIndex < userAnswers.Count && userAnswers[userAnswerIndex].Number == sccuss[questionIndex].ID)
            {
                sccuss[questionIndex].Answer = userAnswers[userAnswerIndex];
                userAnswerIndex++;
            }
        }
    }

    private void CalculateAvoidanceItems()
    {
        calculateImportanceAvoidance();
        calculatePresureAvoidance();
        // should not change the sequence of these two:
        calculateActivityAvoidance();
        calculateSuccessAvoidance();
    }

    private void calculateSuccessAvoidance()
    {
        int noOfYes = 0;

        foreach (int i in this.avoidanceItems)
        {
            if (parts[2].Questions[i - 1].Answer.Ans != null)
                noOfYes++;
        }
        if (noOfYes != 0)
            this.sces_avdc = this.aty_avdc / noOfYes;
    }

    private void calculateActivityAvoidance()
    {
        aty_avdc = 0;
        foreach (int i in avoidanceItems)
        {
            if (Convert.ToInt32(parts[2].Questions[i - 1].Answer.Ans) != 0)
                this.aty_avdc++;
        }
    }

    private void calculatePresureAvoidance()
    {
        pres_avdc = 0;
        foreach (int i in avoidanceItems)
        {
            this.pres_avdc += Convert.ToInt32(parts[1].Questions[i - 1].Answer.Ans);
        }
        this.pres_avdc = this.pres_avdc / 3;
    }

    private void calculateImportanceAvoidance()
    {
        this.imptc_avdc = 0;

        foreach (int i in avoidanceItems)
        {
            this.imptc_avdc += Convert.ToInt32(parts[0].Questions[i - 1].Answer.Ans);
        }

        this.imptc_avdc = this.imptc_avdc / 3;
    }

    public Control generateReport()
    {
        List<Question> _importance = (List<Question>)parts[0].Questions;
        List<Question> _presured = (List<Question>)parts[1].Questions;
        List<Question> _success = (List<Question>)parts[2].Questions;

        conflict = ProcessConflict(_importance, _presured);
        importance = ProcessImportPriciple(_importance);
        presured = ProcessPressured(_presured);
        underAchived = ProcessUnderAchieved(_importance, _success);

        HtmlTable table = new HtmlTable();
        //table.Attributes["border"] = "1";
        HtmlTableRow header = new HtmlTableRow();
        header.Attributes["align"] = "center";
        table.Rows.Add(header);
        HtmlTableCell importantCell = new HtmlTableCell();
        importantCell.InnerHtml = "<h3>Important Priciples</h3>";
        header.Cells.Add(importantCell);
        HtmlTableCell presuredCell = new HtmlTableCell();
        presuredCell.InnerHtml = "<h3>Pressured Priciples</h3>";
        header.Cells.Add(presuredCell);
        table.Rows.Add(header);
        HtmlTableRow tr1;
        for (int i = 0; i < 15 && i < importance.Count && i < presured.Count; i++)
        {
            tr1 = new HtmlTableRow();
            tr1.Attributes["align"] = "left";
            importantCell = new HtmlTableCell();
            presuredCell = new HtmlTableCell();
            importantCell.InnerText = importance[i].No + "." + importance[i].Description;
            presuredCell.InnerText = presured[i].No + "." + presured[i].Description;
            tr1.Cells.Add(importantCell);
            tr1.Cells.Add(presuredCell);
            table.Rows.Add(tr1);
        }
        header = new HtmlTableRow();
        header.Attributes["align"] = "center";
        HtmlTableCell conflictedCell = new HtmlTableCell();
        HtmlTableCell underachivedCell = new HtmlTableCell();
        conflictedCell.InnerHtml = "<h3>Conflicted Principles</h3>";
        underachivedCell.InnerHtml = "<h3>Underachieved Principles</h3>";
        header.Cells.Add(conflictedCell);
        header.Cells.Add(underachivedCell);
        table.Rows.Add(header);
        HtmlTableRow tr2;
        for (int i = 0; i < 15 && i < importance.Count && i < presured.Count; i++)
        {
            tr2 = new HtmlTableRow();
            tr2.Attributes["align"] = "left";
            conflictedCell = new HtmlTableCell();
            underachivedCell = new HtmlTableCell();
            conflictedCell.InnerText = conflict[i].Number + "." + conflict[i].QuestionDescription;
            underachivedCell.InnerText = underAchived[i].Number + "." + underAchived[i].QuestionDescription;
            tr2.Cells.Add(conflictedCell);
            tr2.Cells.Add(underachivedCell);
            table.Rows.Add(tr2);
        }
        control.Controls.Add(table);
        return control;
    }

    private List<Conflict> ProcessConflict(List<Question> _importance, List<Question> _pressure)
    {
        List<Conflict> conflicts = new List<Conflict>();
        for (int i = 0; i < _importance.Count && i < _pressure.Count; i++)
        {
            conflicts.Add(new Conflict(_importance[i], _pressure[i]));
        }
        conflicts.Sort(CompareConflicts);
        return conflicts;
    }

    private List<Question> ProcessPressured(List<Question> _presured)
    {
        // Top 15 most presured principles ( from part 2)
        List<Question> presured = new List<Question>();
        presured.AddRange(_presured);
        presured.Sort(CompareQuestions);
        return presured;
    }

    private List<UnderAchieved> ProcessUnderAchieved(List<Question> _importance, List<Question> _success)
    {
        List<UnderAchieved> underAchieved = new List<UnderAchieved>();
        for (int i = 0; i < _importance.Count; i++)
        {
            //Question t = new 
            underAchieved.Add(new UnderAchieved(_importance[i], _success[i]));
        }
        underAchieved.Sort(CompareUnderAchieved);
        return underAchieved;
    }



    private List<Question> ProcessImportPriciple(List<Question> _importance)
    {
        // Top 15 most import principles ( from part 1)
        List<Question> importance = new List<Question>();
        importance.AddRange(_importance);
        importance.Sort(CompareQuestions);
        return importance;
    }

    #region Properties
    public double ImportanceScore
    {
        get { return importanceScore; }
    }
    public double PressureScore
    {
        get { return pressureScore; }
    }
    public double ActivityScore
    {
        get { return activityScore; }
    }
    public double SuccessScore { get { return successScore; } }

    public double Imptc_avdc { get { return this.imptc_avdc; } }

    public double Pres_avdc { get { return this.pres_avdc; } }

    public double Aty_avdc { get { return this.aty_avdc; } }

    public double Sces_avdc { get { return this.sces_avdc; } }


    public List<Conflict> Conflict { get { return this.conflict; } }
    public List<Question> Importance { get { return this.importance; } }
    public List<Question> Presured { get { return this.presured; } }
    public List<UnderAchieved> UnderAchived { get { return this.underAchived; } }

    #endregion

    #region Private variables

    private double importanceScore;
    private double pressureScore;
    private double activityScore;
    private double successScore;
    private double imptc_avdc;
    private double pres_avdc;
    private double aty_avdc;
    private double sces_avdc;
    #endregion
}
